#include "utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int report_msg(int retcode, const char * msg)
{
    printf(msg);
    return retcode;
}

int report_msg_with_newline(int retcode, const char * msg)
{
    printf(msg);
    printf("\n");
    return retcode;
}

int charbuf_init(CharBuf* cb, int len, int delta)
{
  cb->buf = (char*)malloc(len);
  if (cb->buf) {
	cb->len = len;
	cb->delta = delta;
	charbuf_clear(cb);
	return 1;
  }
  else {
	return report_msg(0, "Not enough memory in inti_charbuf.\n");
  }
}

int charbuf_isempty(CharBuf* cb)
{
    return !(cb->cursor);
}

int charbuf_prolog_of_append(CharBuf* cb, int size)
{
  int empty_space = cb->len-cb->cursor;
  if ( empty_space <= size) {
	int need_extra = size - empty_space;
	int times = need_extra / cb->delta + 1;
	int new_len = cb->len + times * cb->delta;
	char* p = (char*)realloc(cb->buf, new_len);
	if (p) {
	  cb->buf = p;
	  cb->len = new_len;
	  return 1;
	}
	else {
	  return report_msg(0, "Not enough memory in charbuf_prolog_of_append.\n");
	}
  }
  else {
	return 1;
  }
}

int charbuf_append_char(CharBuf* cb, char ch)
{
  if (charbuf_prolog_of_append(cb, 1)) {
	cb->buf[cb->cursor] = ch;
	cb->cursor += 1;
	charbuf_zerotail(cb);
  }
  else {
	return 0;
  }
}

int charbuf_append_substr(CharBuf* cb, const char* src, int start, int end)
{
    if (charbuf_prolog_of_append(cb, end-start)) {
        memcpy(cb->buf + cb->cursor, src+start, end-start);
        cb->cursor += end-start;
        charbuf_zerotail(cb);
        return 1;
    }
    else {
        return 0;
    }
}

int charbuf_append_str(CharBuf* cb, const char* src)
{
    return charbuf_append_substr(cb, src, 0, strlen(src));
}

int charbuf_fill_substr(CharBuf* cb, const char* src, int start, int end)
{
    charbuf_clear(cb);
    return charbuf_append_substr(cb, src, start, end);
}

int charbuf_fill_str(CharBuf* cb, const char* src)
{
  return charbuf_fill_substr(cb, src, 0, strlen(src));
}

void charbuf_clear(CharBuf* cb)
{
    cb->cursor = 0;
    charbuf_zerotail(cb);
}

void charbuf_zerotail(CharBuf* cb)
{
    cb->buf[cb->cursor] = 0;
}

void charbuf_free(CharBuf* cb)
{
    free(cb->buf);
    cb->cursor=0;
    cb->len=0;
    cb->buf=0;
}
